package com.bestcem.xm.ticket.service.manager.notify;

import cn.hutool.core.lang.ObjectId;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.ticket.constant.Constants;
import com.bestcem.xm.ticket.dao.TicketConfigDao;
import com.bestcem.xm.ticket.entity.mongo.Ticket;
import com.bestcem.xm.ticket.entity.mongo.TicketConfig;
import com.bestcem.xm.ticket.enums.TicketNotifyChannelEnum;
import com.bestcem.xm.ticket.enums.TicketOperationTypeEnum;
import com.bestcem.xm.ticket.enums.TicketTypeEnum;
import com.bestcem.xm.ticket.grpc.client.TicketBaseQdesGrpcService;
import com.bestcem.xm.ticket.grpc.client.TicketBaseUserGrpcService;
import com.bestcem.xm.ticket.grpc.client.dto.qdes.QStructDTO;
import com.bestcem.xm.ticket.grpc.client.dto.user.OrganizationDTO;
import com.bestcem.xm.ticket.service.manager.notify.dto.NotifyMessageDTO;
import com.bestcem.xm.ticket.service.manager.notify.dto.RegexDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Nonnull;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.bestcem.xm.common.core.uitls.DateUtil.BEIJING_ZONE;

/**
 * 获取工单通知信息填充数据 工具类
 *
 * @author XiaoYunSong <ys.xiao@idiaoyan.com>
 * @version v1.0
 * @date 2021/11/22 14:35
 */
@Slf4j
@Component
public class ContentManager {

    @Resource
    private TicketBaseUserGrpcService ticketBaseUserGrpcService;
    @Resource
    private TicketBaseQdesGrpcService ticketBaseQdesGrpcService;

    @Resource
    private TicketConfigDao ticketConfigDao;

    @Resource
    private SurveyParseManager surveyParseManager;

    /**
     * 协议配置
     */
    @Value("${app.ticket.notify-protocol:http}")
    private String notifyProtocol;
    /**
     * 服务器配置
     */
    @Value("${app.ticket.notify-url:xm-test.bestcem.com}")
    private String notifyUrl;

    /**
     * 用于字段不存在时的展示
     */
    protected static final String NONE = "无";
    /**
     * 通用时间格式
     */
    protected static final String DATETIME_PATTERN = "yyyy/MM/dd HH:mm";
    /**
     * 邮件发送时间格式
     */
    protected static final String SEND_DATETIME_PATTERN = "yyyy年MM月dd日";
    /**
     * 用于 文字链接 的正则匹配
     */
    protected static final Pattern TEXT_URL_PATTERN = Pattern.compile(FiledConstant.Email.TEXT_URL_REGEX);
    /**
     * 用于 问卷题目 的正则匹配
     */
    protected static final Pattern QUESTION_PATTERN = Pattern.compile(FiledConstant.Email.ANSWER_QUESTION_REGEX);
    /**
     * 用于 匹配文本中的img标签 的正则匹配
     */
    protected static final Pattern IMG_PATTERN = Pattern.compile("<img(.*?)>");
    /**
     * 用于 匹配文本中的video标签 的正则匹配
     */
    protected static final Pattern VIDEO_PATTERN = Pattern.compile("<video(.*?)/video>");
    /**
     * 用于 匹配文本中的换行 的正则匹配
     */
    protected static final Pattern WRAP_PATTERN = Pattern.compile("[\\t|\\r|\\n]");
    /**
     * 用于问卷标题提取的正则匹配
     */
    protected static final Pattern TEXT_PATTERN = Pattern.compile("<p.*?>(.*?)</p>");


    /**
     * 渲染短信正文需要的数据 (消息库版)
     *
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/9 16:09
     */
    @Nonnull
    protected Map<String, String> getSmsData(Ticket ticket, String sysName) {
        Map<String, String> result = new HashMap<>();

        // 获取 工单URL
        String url = getTicketUrl(ticket, TicketNotifyChannelEnum.SMS);
        // 获取 规则/工单名称; 长度限制15个字符
        String ruleName = getRuleName(ticket);
        if (ruleName.length() > 15) {
            ruleName = ruleName.substring(0, 15);
        }
        // 获取 项目名称
        String projectName = ticket.getSurveyTitle();
        if (!ObjectUtils.isEmpty(projectName)) {
            if (projectName.length() > 10) {
                projectName = projectName.substring(0, 10);
            }
        }
        // 获取 问卷标题
        String surveyTitle = getSurveyName(ticket.getSurveyId());
        if (surveyTitle.length() > 10) {
            surveyTitle = surveyTitle.substring(0, 10);
        }
        // 获取 工单触发条件名称; 用" | "隔开, 最长20个字符; 超过20个字, 展示为  17个字符的内容+3个字符的"."
        String triggerName = NONE;
        if (!CollectionUtils.isEmpty(ticket.getTriggerNames())) {
            triggerName = String.join(" | ", ticket.getTriggerNames());
            if (triggerName.length() > 20) {
                triggerName = triggerName.substring(0, 17) + "...";
            }
        }


        // 问卷标题
        result.put(FiledConstant.Sms.SURVEY_NAME, surveyTitle);
        // 项目名称
        result.put(FiledConstant.Sms.PROJECT_NAME, projectName);
        // 系统名称
        if (Objects.nonNull(sysName)) {
            if (sysName.length() > 15) {
                sysName = sysName.substring(0, 15);
            }
        }
        result.put(FiledConstant.Sms.SYSTEM_NAME, sysName);

        // 规则/工单名称
        result.put(FiledConstant.Sms.RULE_NAME, ruleName);
        // 编号
        result.put(FiledConstant.Sms.TICKET_NO, ticket.getTicketNo());
        // 工单预警详情链接, 后面的空格不要动, 不然URL有可能会和后面的字符一起识别为链接
        result.put(FiledConstant.Sms.URL, url + "   ");
        // 生成时间
        result.put(FiledConstant.Sms.CREATE_TIME, formatDate(ticket.getCreatedDate()));
        // 处理逾期时间
        result.put(FiledConstant.Sms.FOLLOW_OVERDUE_TIME, formatDate(timeConvert(ticket.getFollowDeadline())));
        // 工单触发条件名称
        result.put(FiledConstant.Sms.TRIGGER_NAME, triggerName);

        return result;
    }


    /**
     * 渲染邮件正文需要的数据 (消息库版)
     *
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/9 16:09
     */
    @Nonnull
    protected Map<String, String> getEmailData(@Nonnull Ticket ticket, String sysName, @Nonnull NotifyMessageDTO message) {
        Map<String, String> result = new HashMap<>();

        // 获取 工单URL
        String url = getTicketUrl(ticket, TicketNotifyChannelEnum.EMAIL);
        // 获取 规则/工单名称
        String ruleName = getRuleName(ticket);
        // 获取 工单触发条件名称; 用" | "隔开, 最长20个字符; 超过20个字, 展示为  17个字符的内容+3个字符的"."
        String triggerName = NONE;
        if (!CollectionUtils.isEmpty(ticket.getTriggerNames())) {
            triggerName = String.join(" | ", ticket.getTriggerNames());
            if (triggerName.length() > 20) {
                triggerName = triggerName.substring(0, 17) + "...";
            }
        }


        // 问卷名称
        result.put(FiledConstant.Email.SURVEY_NAME, getSurveyName(ticket.getSurveyId()));
        // 项目名称
        result.put(FiledConstant.Email.PROJECT_NAME, ticket.getSurveyTitle());
        // 系统名称
        result.put(FiledConstant.Email.SYSTEM_NAME, sysName);

        // 规则/工单名称
        result.put(FiledConstant.Email.RULE_NAME, ruleName);
        // 编号
        result.put(FiledConstant.Email.TICKET_NO, ticket.getTicketNo());
        // 原始链接
        result.put(FiledConstant.Email.URL, url);
        // 生成时间
        result.put(FiledConstant.Email.CREATE_TIME, formatDate(ticket.getCreatedDate()));
        // 处理逾期时间
        result.put(FiledConstant.Email.FOLLOW_OVERDUE_TIME, formatDate(timeConvert(ticket.getFollowDeadline())));
        // 工单触发条件名称
        result.put(FiledConstant.Email.TRIGGER_NAME, triggerName);

        // 发邮件日期
        result.put(FiledConstant.Email.SEND_TIME, formatSendDate(new Date()));

        // 主题中的文字链接
        List<RegexDTO> subjectText = getTextUrlContent(message.getSubject());
        for (RegexDTO dto : subjectText) {
            String text = dto.getText();
            if (Objects.nonNull(text) && text.length() > 10) {
                text = text.substring(0, 10);
            }
            result.put(dto.getField(), text);
        }
        // 内容中的文字链接
        List<RegexDTO> contentText = getTextUrlContent(message.getContent());
        for (RegexDTO dto : contentText) {
            String text = dto.getText();
            if (Objects.nonNull(text) && text.length() > 10) {
                text = text.substring(0, 10);
            }
            result.put(dto.getField(), text);
        }

        /* 所有字段 */
        // 提取 问卷题目 字段
        List<RegexDTO> allQuestions = new ArrayList<>();
        // 主题中的问卷题目
        allQuestions.addAll(getQuestionContent(message.getSubject()));
        // 内容中的问卷题目
        allQuestions.addAll(getQuestionContent(message.getContent()));
        // 所有题目的 序号
        Set<String> allCid = allQuestions.stream().map(RegexDTO::getText).collect(Collectors.toSet());
        // 展示的题目
        Map<String, String> answers = surveyParseManager.getNotifyQuestion(ticket, allCid);
        for (RegexDTO dto : allQuestions) {
            // 去除问题中的各种奇怪标签
            result.put(dto.getField(), removeAttachment(answers.get(dto.getText())));
        }

        return result;
    }


    /**
     * 渲染飞书正文需要的数据 (触发条件名称版)
     *
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/2/18 11:29
     */
    @Nonnull
    protected Map<String, String> getFeiShuData(Ticket ticket) {
        Map<String, String> result = new HashMap<>();

        // 获取 工单URL
        String url = getTicketUrl(ticket, TicketNotifyChannelEnum.FEI_SHU);
        // 获取 规则/工单名称
        String ruleName = getRuleName(ticket);
        // 获取 项目名称
        String projectName = ticket.getSurveyTitle();
        if (!ObjectUtils.isEmpty(projectName)) {
            projectName = "【" + projectName + "】";
        }


        // 规则/工单名称
        result.put(FiledConstant.FeiShu.TICKET_CONFIG_NAME, ruleName);
        // 项目名称
        result.put(FiledConstant.FeiShu.PROJECT_NAME, projectName);
        // 编号
        result.put(FiledConstant.FeiShu.TICKET_NO, ticket.getTicketNo());
        // 工单预警详情链接
        result.put(FiledConstant.FeiShu.URL, url);
        // 处理逾期时间
        result.put(FiledConstant.FeiShu.FOLLOW_OVERDUE_TIME, formatDate(timeConvert(ticket.getFollowDeadline())));
        // 工单触发条件名称; 用" | "隔开, 最长20个字符; 超过20个字, 展示为  17个字符的内容+3个字符的"."
        if (!CollectionUtils.isEmpty(ticket.getTriggerNames())) {
            String triggerNames = String.join(" | ", ticket.getTriggerNames());
            if (triggerNames.length() > 20) {
                result.put(FiledConstant.FeiShu.TRIGGER_NAME, triggerNames.substring(0, 17) + "...");
            } else {
                result.put(FiledConstant.FeiShu.TRIGGER_NAME, triggerNames);
            }
        }

        return result;
    }


    /**
     * 渲染钉钉正文需要的数据
     *
     * @param ticket 工单信息
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/17 13:59
     */
    @Nonnull
    protected Map<String, String> getDingTalkData(Ticket ticket) {
        Map<String, String> result = new HashMap<>();

        // 获取 工单URL
        String url = getDingTalkUrl(ticket);
        // 获取 工单规则名称/工单名称
        String ruleName = getRuleName(ticket);
        // 获取 项目名称
        String projectName = ticket.getSurveyTitle();
        if (!ObjectUtils.isEmpty(projectName)) {
            projectName = "【" + projectName + "】";
        }
        // 获取 工单触发条件名称; 用" | "隔开, 最长20个字符; 超过20个字, 展示为  17个字符的内容+3个字符的"."
        String triggerName = Constants.BLANK;
        if (!CollectionUtils.isEmpty(ticket.getTriggerNames())) {
            triggerName = String.join(" | ", ticket.getTriggerNames());
            if (triggerName.length() > 20) {
                triggerName = triggerName.substring(0, 17) + "...";
            }
            triggerName = "触发条件名称：" + triggerName;
        }


        // 问卷名称
        result.put(FiledConstant.DingTalk.SURVEY_TITLE, Optional.ofNullable(projectName).orElse(Constants.BLANK));
        // 编号
        result.put(FiledConstant.DingTalk.TICKET_NO, Optional.ofNullable(ticket.getTicketNo()).orElse(Constants.BLANK));
        // 规则名称
        result.put(FiledConstant.DingTalk.TICKET_CONFIG_NAME, ruleName);
        // 处理逾期时间
        result.put(FiledConstant.DingTalk.OVERDUE_TIME, formatDate(timeConvert(ticket.getFollowDeadline())));
        // 工单预警详情链接 (这里要注意, python那边会在这个链接后边拼一个钉钉的免登陆参数, 我们的链接不要影响后续参数的拼接)
        result.put(FiledConstant.DingTalk.TICKET_URL, url);
        // 工单触发条件名称
        result.put(FiledConstant.DingTalk.TRIGGER_NAME, triggerName);

        return result;
    }

    /**
     * 渲染企业微信正文需要的数据
     *
     * @param ticket 工单信息
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/17 13:59
     */
    @Nonnull
    protected Map<String, String> getWechatWorkData(Ticket ticket) {
        Map<String, String> result = new LinkedHashMap<>();

        // 获取 工单规则名称/工单名称
        String ruleName = getRuleName(ticket);

        // !!! 这里每个字段的put顺序不要动, 产品有要求的
        // 项目名称
        String surveyTitle = ticket.getSurveyTitle();
        if (!ObjectUtils.isEmpty(surveyTitle)) {
            if (surveyTitle.length() > 28) {
                surveyTitle = surveyTitle.substring(0, 28);
            }
            result.put(FiledConstant.WechatWork.SURVEY_TITLE, surveyTitle + "项目");
        }
        if (TicketTypeEnum.NEED_DEAL.getIndex().equals(ticket.getType())) {
            // 工单编号
            result.put(FiledConstant.WechatWork.TICKET_NO, Optional.ofNullable(ticket.getTicketNo()).orElse(Constants.BLANK));
            // 处理逾期时间
            result.put(FiledConstant.WechatWork.OVERDUE_TIME, formatDate(timeConvert(ticket.getFollowDeadline())));
        } else {
            // 预警编号
            result.put(FiledConstant.WechatWork.ONLY_NOTIFY_NO, Optional.ofNullable(ticket.getTicketNo()).orElse(Constants.BLANK));
        }
        // 规则名称/工单名称
        result.put(FiledConstant.WechatWork.TICKET_CONFIG_NAME, ruleName);
        // 工单触发条件名称; 用" | "隔开, 最长20个字符; 超过20个字, 展示为  17个字符的内容+3个字符的"."
        if (!CollectionUtils.isEmpty(ticket.getTriggerNames())) {
            String triggerName = String.join(" | ", ticket.getTriggerNames());
            if (triggerName.length() > 20) {
                triggerName = triggerName.substring(0, 17) + "...";
            }
            result.put(FiledConstant.WechatWork.TRIGGER_NAME, triggerName);
        }

        return result;
    }


    /**
     * 获取工单详情链接
     *
     * @param ticket  工单信息
     * @param channel 通知渠道
     * @return String 工单详情链接
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/1 18:11
     */
    @Nonnull
    private String getTicketUrl(Ticket ticket, TicketNotifyChannelEnum channel) {
        return notifyProtocol + "://" + notifyUrl + "/issue/detail?id=" + ticket.getId() + "&channel=" + channel.getIndex();
    }


    /**
     * 获取 钉钉消息中的工单详情链接
     *
     * @param ticket 工单信息
     * @return String 工单钉钉详情链接
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/30 17:40
     */
    @Nonnull
    private String getDingTalkUrl(Ticket ticket) {
        StringBuilder urlBuilder = new StringBuilder();
        OrganizationDTO organizationDTO = ticketBaseUserGrpcService.getOrganization(ticket.getOrgId());
        String orgCode = Constants.BLANK;
        if (Objects.nonNull(organizationDTO)) {
            orgCode = organizationDTO.getCode();
        }
        urlBuilder.append(notifyProtocol);
        urlBuilder.append("://");
        urlBuilder.append("www.");
        urlBuilder.append(notifyUrl);
        urlBuilder.append("/mp/cem/?");
        urlBuilder.append("&orgCode=").append(orgCode);
        urlBuilder.append("&channel=dingtalk");
        urlBuilder.append("&ticketId=").append(ticket.getId());
        urlBuilder.append("#/pages/work-order/index?");
        urlBuilder.append("&ticketId=").append(ticket.getId());
        return urlBuilder.toString();
    }


    /**
     * 获取制定公司的域名 orgcode.xxx.com，考虑到私有部署的情况做了一些调整
     *
     * @param orgCode 公司 code
     * @return String
     * @author gy.liu
     * @date 2021/8/23
     */
    @Nonnull
    private String getOrgUrl(String orgCode) {
        StringBuilder url = new StringBuilder();
        url.append(notifyProtocol);
        url.append("://");
        if (!ObjectUtils.isEmpty(orgCode) && !Constants.BLANK.equals(orgCode)) {
            url.append(orgCode);
            url.append(".");
        }
        url.append(notifyUrl);
        return url.toString();
    }


    /**
     * Date 格式化 yyyy/MM/dd HH:mm
     *
     * @param date date
     * @return Time string in {@link ContentManager#DATETIME_PATTERN} format
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:25
     */
    @Nonnull
    private static String formatDate(Date date) {
        if (Objects.isNull(date)) {
            return NONE;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN);
        return simpleDateFormat.format(date);
    }


    /**
     * Date 格式化 yyyy年MM月dd日
     * 用于工单通知 邮件发送时间 字段
     *
     * @param date date
     * @return Time string in {@link ContentManager#SEND_DATETIME_PATTERN} format
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:25
     */
    @Nonnull
    private static String formatSendDate(Date date) {
        if (Objects.isNull(date)) {
            return NONE;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(SEND_DATETIME_PATTERN);
        return simpleDateFormat.format(date);
    }


    /**
     * 提取 通知模板 中的 文字链接 字段信息
     *
     * @param template 通知模板
     * @return 用户输入的 文字链接 字段
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:25
     */
    @Nonnull
    private static List<RegexDTO> getTextUrlContent(String template) {
        if (ObjectUtils.isEmpty(template)) {
            return new ArrayList<>();
        }

        List<RegexDTO> result = new ArrayList<>();
        Matcher matcher = TEXT_URL_PATTERN.matcher(template);
        // 匹配所有的 文字链接 字段
        while (matcher.find()) {
            if (matcher.groupCount() <= 1) {
                result.add(new RegexDTO(matcher.group(0), matcher.group(1)));
            }
        }
        return result;
    }


    /**
     * 提取 通知模板 中的 问卷题目 字段信息
     *
     * @param template 通知模板
     * @return 用户输入的 文字链接 字段
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:25
     */
    @Nonnull
    private static List<RegexDTO> getQuestionContent(String template) {
        if (ObjectUtils.isEmpty(template)) {
            return new ArrayList<>();
        }

        List<RegexDTO> result = new ArrayList<>();
        Matcher matcher = QUESTION_PATTERN.matcher(template);
        // 匹配所有的 问卷题目 字段
        while (matcher.find()) {
            if (matcher.groupCount() <= 1) {
                result.add(new RegexDTO(matcher.group(0), matcher.group(1)));
            }
        }
        return result;
    }


    /**
     * 获取问卷的内部标题
     *
     * @param surveyId 问卷id
     * @return 问卷的内部标题
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 15:09
     */
    @Nonnull
    private String getSurveyName(String surveyId) {
        if (!ObjectId.isValid(surveyId)) {
            return Constants.BLANK;
        }
        List<QStructDTO> dtoList = ticketBaseQdesGrpcService.ListQStruct(surveyId);
        if (CollectionUtils.isEmpty(dtoList)) {
            return Constants.BLANK;
        }
        if (dtoList.size() < 1) {
            return Constants.BLANK;
        }
        QStructDTO dto = dtoList.get(0);
        String dataJson = dto.getData();
        try {
            JSONObject data = JSONObject.parseObject(dataJson);
            if (!data.containsKey("desc_begin_page")) {
                return Constants.BLANK;
            }
            JSONObject descBeginPage = data.getJSONObject("desc_begin_page");
            if (!descBeginPage.containsKey("content")) {
                return Constants.BLANK;
            }
            JSONObject content = descBeginPage.getJSONObject("content");
            if (!content.containsKey("text")) {
                return Constants.BLANK;
            }

            return removeSurveyTitleStyle(content.getString("text"));
        } catch (Exception e) {
            return Constants.BLANK;
        }
    }


    /**
     * 去除文本中的各种奇怪的 html 标签
     *
     * @param text 目标文本
     * @return 去除后的文本
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/12/1 10:49
     */
    @Nonnull
    public static String removeAttachment(String text) {
        if (ObjectUtils.isEmpty(text)) {
            return Constants.BLANK;
        }
        Matcher matcher;
        matcher = WRAP_PATTERN.matcher(text);
        text = matcher.replaceAll("");
        matcher = IMG_PATTERN.matcher(text);
        text = matcher.replaceAll("");
        matcher = VIDEO_PATTERN.matcher(text);
        return matcher.replaceAll("");
    }


    /**
     * 获取工单 规则/工单名称
     *
     * @param ticket 工单信息
     * @return 规则/工单名称
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/2/24 18:29
     */
    @Nonnull
    public String getRuleName(Ticket ticket) {
        String ruleName = "";
        if (TicketOperationTypeEnum.MANUAL.getIndex().equals(ticket.getOperationType())) {
            ruleName = ticket.getName();
        } else {
            TicketConfig ticketConfig = ticketConfigDao.findById(ticket.getTicketConfigId());
            if (Objects.nonNull(ticketConfig)) {
                ruleName = ticketConfig.getTitle();
            }
        }
        if (ObjectUtils.isEmpty(ruleName)) {
            ruleName = NONE;
        }
        return ruleName;
    }


    public static String removeSurveyTitleStyle(String text) {
        if (ObjectUtils.isEmpty(text)) {
            return Constants.BLANK;
        }
        Matcher matcher = TEXT_PATTERN.matcher(text);
        // 匹配所有的 文字链接 字段
        while (matcher.find()) {
            if (matcher.groupCount() <= 1) {
                return matcher.group(1);
            }
        }
        return text;
    }


    public Date timeConvert(Date date) {
        if (ObjectUtils.isEmpty(date)) {
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), BEIJING_ZONE);
        return Date.from(localDateTime.toInstant(BEIJING_ZONE));
    }

}
